package com.tomtop.core.logging;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.tomtop.core.utils.JSONUtils;
import com.tomtop.core.utils.ListUtils;
import com.tomtop.core.utils.MapUtils;

@Configuration
public class RunTimeLog implements InitializingBean{

	private static final ThreadLocal<Long> beginTime=new ThreadLocal<Long>(){protected Long initialValue() {return System.currentTimeMillis();};};
	private final static Logger LOGGER = LoggerFactory.getLogger("tomtop.time.log");
	
	private static Map<String,Integer> timeScale=MapUtils.<String,Integer>n().a("off", 1000).a("trace", 10).a("debug", 100).a("info", 200).a("warn", 2000).a("error", 8000).to();
	private static List<Entry<String, Integer>> timeScaleList ;
	private static int offtime ;
	static{
		init(timeScale);
	}

	private static void init(Map<String, Integer> map){
		timeScale=MapUtils.n(map).filter((k,v)->v!=null).to();
		Integer offtime_=timeScale.remove("off");
		offtime=offtime_==null?-1:offtime_;
		timeScaleList= ListUtils.n(timeScale.entrySet()).filter(t->t.getValue()!=null).order(t->t.getValue()).to();
	}
	
	@ConfigurationProperties("logging.timescale")
	@Bean Map<String,Integer> timeScale() { timeScale.clear(); return timeScale; }
	
	public static final void clear(){
		beginTime.remove();
	}
	
	public static final void bedin(){
		beginTime.set(System.currentTimeMillis());
	}
	
	private static long getRuntime() {
		long bedin = beginTime.get();
		long end=System.currentTimeMillis();
		beginTime.set(end);
		return end-bedin;
	}
	
	public static final void log( String f,Object ... args){
		log(getRuntime(), f, args);
	}
	
	public static final void log(long runtime,String f,Object ... args){
		if(runtime==0 || f==null || offtime>runtime || timeScaleList.isEmpty()){
			return;
		}
		Entry<String, Integer> suitmin=null;
		for (Entry<String, Integer> entry : timeScaleList) {
			if(entry.getValue()>runtime)
				break;
			suitmin=entry;
		}
		StringBuffer format= new StringBuffer("执行时间:").append(runtime).append("毫秒   ").append(f);
		output(suitmin, format.toString(), args);
	}
	
	private static void output(Entry<String, Integer> suitmin,String f,Object ... args) {
		if(suitmin==null){
			LOGGER.debug(f,args);
		}else{
			switch (suitmin.getKey()) {
			case "trace":
				LOGGER.trace(f,args);
				break;
			case "debug":
				LOGGER.debug(f,args);
				break;
			case "info":
				LOGGER.info(f,args);
				break;
			case "warn":
				LOGGER.warn(f,args);
				break;
			case "error":
				LOGGER.error(f,args);
				break;
			default:
				LOGGER.info(f,args);
				break;
			}
		}
	}
	
	@Override
	public void afterPropertiesSet() throws Exception {
		 init(timeScale());
		LOGGER.info("api调用日志输出时间参数配置信息{} 日志最少输出的时间 {}",JSONUtils.toJSONString(timeScaleList),offtime);
	}
}
